-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Refactor tile coverage to support level of detail #16335
Conversation
|
||
const double numTiles = std::pow(2.0, z); | ||
const double worldSize = Projection::worldSize(state.getScale()); | ||
const uint8_t minZoom = state.getPitch() <= (60.0 / 180.0) * M_PI ? z : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line controls if tiles from different zoom levels can be returned. Level-of-detail functionality is disabled when pitch is <= 60 degrees.
src/mbgl/util/bounding_volumes.hpp
Outdated
// It is possible run only edge cases that were not covered in intersects() | ||
IntersectionResult intersectsPrecise(const AABB& aabb, bool edgeCasesOnly = false) const; | ||
|
||
inline const std::array<vec3, 8>& getPoints() const { return points; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: inline
is not needed
src/mbgl/util/bounding_volumes.hpp
Outdated
IntersectionResult intersectsPrecise(const AABB& aabb, bool edgeCasesOnly = false) const; | ||
|
||
inline const std::array<vec3, 8>& getPoints() const { return points; } | ||
inline const std::array<vec4, 6>& getPlanes() const { return planes; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
src/mbgl/util/bounding_volumes.cpp
Outdated
|
||
std::array<vec4, 6> frustumPlanes; | ||
|
||
for (int i = 0; i < (int)frustumPlanePointIndices.size(); i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ++i
why not std::size_t
Looks great, but let @astojilj to take a look before merge |
In case that this was measured using some benchmark, how much is "tile cover update" budget per frame affected by this on example mobile platform? |
f0dc2a8
to
41a50ac
Compare
if (result == IntersectionResult::Separate) return result; | ||
} | ||
|
||
const std::array<vec3, 4> aabbPoints = {vec3{aabb.min[0], aabb.min[1], 0.0}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could alloc and copy here get removed, and add methods to access min and max also for dim 2?
EDIT: For AABB we store min & max vectors and in addition, for every AABB we construct aabbPoints. Might help performance if allocate one only (whichever fits algorithm better) and reduce copies...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All these arrays are stack allocated so the only cost should be variable initialization.
Z-dimension is redundant as all tiles are on the xy-plane and leaving z out reduces the number of required intersection tests. This could be updated if we ever have a need for elevation.
Corner points of the aabb could be pre-generated but it would be premature optimization in this case. Intersection tests are performed once per aabb and moving the generation of points to constructor wouldn't remove any logic. Frustum::intersects
also requires a w
component whereas Frustum::intersectsPrecise
does not.
LGTM after documenting performance impact on one frame. |
8dbc84d
to
aab6608
Compare
aab6608
to
1c94e0e
Compare
I profiled the code on my quite fast laptop in the following location: Tests were done by rendering a map 60fps for 10 seconds using "streets-v11" style. Time spent in |
This pull request implements a more versatile logic for finding visible tiles on the screen. Intersection tests have been extended to 3D space by using bounding volumes for tiles and camera instead of projecting everything to zero elevation plane. Tile pyramid is traversed depth-first while preserving distances to tiles allowing an easy support for a level-of-detail. Even though the distance based lod is supported by this implementation, this PR has no visible effect for the user. Level of detail logic is deactive when pitch is <= 60 degrees.
The native implementation follows the javascript one (mapbox/mapbox-gl-js#8975) with few exceptions:
Performance-wise the new implementation is few orders of magnitude slower than the original one. In a bigger picture the difference is not noticeable. I could see an increase of 5-15% time spent in TilePyramid::Update. Perhaps it's worth of discussion if the new tileCover should be a separate function and optional unless explicitly activated?
TODO